#include "SdpModule.h"
#include "XmlReader.h"
#include "ConferenceModule.h"

#include "resip/dum/MasterProfile.hxx"
#include "rutil/DnsUtil.hxx"

#include <stdio.h>
#include <string.h>


#include <sstream>

using namespace std;
using namespace resip;

SdpModule::SdpModule()
{
	initialize();
}

SdpModule::~SdpModule()
{
	cleanup();
}

void SdpModule::initialize()
{
	;
}

void SdpModule::initializeConference()
{
	m_sendModule = new ConferenceModule;
	m_receiveModule = new ConferenceModule;

	m_sendModule->setMode(1);
	m_receiveModule->setMode(2);

	m_sendModule->setBasePort(m_otherSdpData.audioPort);
	m_sendModule->setPort(m_sdpData.audioPort);

	m_receiveModule->setBasePort(m_sdpData.audioPort );
	m_receiveModule->setPort(m_otherSdpData.audioPort);

	uint8_t m_otherIp[4];
	uint8_t m_myIp[4];	
	

	char * ipPointer = new char[strlen(m_otherSdpData.baseIP.c_str() )+1];
	strcpy( ipPointer, m_otherSdpData.baseIP.c_str() );
	cout << "IP in setten van conference...\n";

	cout << ipPointer;
	for(int i = 0; i < 4; ++i)
	{
		strcat(ipPointer,".");
		m_otherIp[i] = atoi(ipPointer);
	}

	ipPointer = new char[strlen(m_sdpData.baseIP.c_str() )+1];
	strcpy( ipPointer, m_sdpData.baseIP.c_str() );
	cout << "IP in setten van conference...\n";

	cout << ipPointer;
	for(int i = 0; i < 4; ++i)
	{
		strcat(ipPointer,".");
		m_myIp[i] = atoi(ipPointer);
	}

	m_sendModule->setIp(m_otherIp);

	cout << m_myIp[4];
	m_receiveModule->setIp(m_myIp);
}

void SdpModule::cleanup()
{

}

void SdpModule::readCodecFile(std::string file)
{
	XmlReader reader;
	reader.parseCodecFile(file, m_sdpData);
}

string SdpModule::createSdpOffer()
{
	stringstream out;

	out << "v=" << m_sdpData.version << "\r\n";
	out << "o=" << m_sdpData.username << " " << m_sdpData.sessionId << " " << m_sdpData.sessionVersion << " IN IP4 " << m_sdpData.baseIP.substr(0, m_sdpData.baseIP.length())<< "\r\n"; 
	out << "s=" << m_sdpData.sessionName << "\r\n";
	out << "c=IN IP4 " << m_sdpData.mediaIP << "\r\n";
	out << "t=" << m_sdpData.startTime << " " << m_sdpData.stopTime << "\r\n";
	out << "a=sendrecv\r\n"; 
	out << "m=audio " << m_sdpData.audioPort << " RTP/AVP";

	for( int i=0 ; i < m_sdpData.m_codecs.size() ; ++i )
		if( m_sdpData.m_codecs[i]->type == AUDIO )
		{
			cout << "AUDIO Codec TOEVOEGEN\n";
			out << " " << m_sdpData.m_codecs[i]->payload;
		}

	out << "\r\n";

	cout << out.str();

	return out.str();
}

bool SdpModule::acceptSdpOffer(const resip::SdpContents &sdpContents)
{
	bool result = true;

	//create antwoord 
	readCodecFile("codecs.xml");

	cout << "Accept sdp offers!!!!\n";
	cout << "Controleversie:\n" << sdpContents.getBodyData().c_str();
	Data m_data = sdpContents.getBodyData();

	char * strPointer;
	char * linePointer;

	try
	{
		strPointer = strtok( (char*)m_data.c_str() ,"\r\n");
		while( strPointer != NULL )
		{
			cout << "Lijntje: " << strPointer << endl;
			char * newLine = new char[strlen(strPointer) -1];
			strcpy(newLine,strPointer);
			parseSdpLine(newLine);

			strPointer = strtok( NULL ,"\r\n");

		}
		
	}
	catch (ParseException e)
	{
		cout << "ERROR: " << e.getMessage();
	}


	// parsen audio info!!!!
	for(int i = 0; i < codecPars.size(); ++i)
	{
		cout << "CODECPARSER: " << codecPars[i].c_str() << endl;

		char * codecStringPtr = strtok((char*) (codecPars[i].c_str() ), ":");
		string type = codecStringPtr;

		

		if(strcmp(type.c_str(), "rtpmap") == 0)
		{
			codecStringPtr = strtok(NULL," ");
			int payload = atoi(codecStringPtr);
			
			for(int j = 0; j < m_otherSdpData.m_codecs.size(); ++j)
			{
				if( (m_otherSdpData.m_codecs[j])->payload == payload)
				{
					codecStringPtr = strtok(NULL,"/");
					(m_otherSdpData.m_codecs[j])->name = codecStringPtr;
					
					codecStringPtr = strtok(NULL,"/");
					(m_otherSdpData.m_codecs[j])->clockrate = atoi(codecStringPtr);

					codecStringPtr = strtok(NULL, "/");
					if(codecStringPtr != NULL)
						(m_otherSdpData.m_codecs[j])->nrChannels = atoi(codecStringPtr);
					else
						(m_otherSdpData.m_codecs[j])->nrChannels = 1;
				}
			}
		}
		

	}
	// opkuisen tijdelijke codecresults
	while(codecPars.size() > 0)
		codecPars.pop_back();

	cout << "Vergelijken van codecs...\n";
	// vergelijken van codex die we hier hebben met de andere
	bool codecFound = false;
	int targetCodec = -1;

	//aanmaken eigen bericht
	
	cout << "Grootte: " << m_sdpData.m_codecs.size();

	for(int i = 0; i < m_otherSdpData.m_codecs.size()  && !codecFound; ++i)
	{
		for(int j = 0; j < m_sdpData.m_codecs.size() && !codecFound; ++j )
		{
			if(m_otherSdpData.m_codecs[i]->payload  == m_sdpData.m_codecs[j]->payload)
			{
				cout << "GELIJKE PAYLOAD GEVONDEN " << m_otherSdpData.m_codecs[i]->payload;
				targetCodec = j;
				codecFound = true;
			}
		}
	}


	cout << "De resultaten van de parsing: \n";
	cout << "Version= " << m_otherSdpData.version << endl;
	cout << "Username = " << m_otherSdpData.username << endl;
	cout << "SessionId = " << m_otherSdpData.sessionId << endl;
	cout << "SessionVersion = " << m_otherSdpData.sessionVersion << endl;
	cout << "Base IP = " << m_otherSdpData.baseIP << endl;
	cout << "Session name = "  << m_otherSdpData.sessionName << endl;

	for(int i = 0; i < m_otherSdpData.m_codecs.size();++i)
	{
		cout << "Codec " << i << ": \n" << "Payload: " << (m_otherSdpData.m_codecs[i])->payload << endl;
		cout << "Name: " << (m_otherSdpData.m_codecs[i])->name << endl;
		cout << "Clockrate: " << (m_otherSdpData.m_codecs[i])->clockrate << endl;
		cout << "Channels: " << (m_otherSdpData.m_codecs[i])->nrChannels << endl;
		
	}

	if(targetCodec < 0)
	{
		cout << "GEEN OVEREENKOMENDE PAYLOAD!\n";
		result = false;
	}
	else
	{
		initializeConference();
		m_sendModule->setCodec(m_sdpData.m_codecs[targetCodec]->payload);
		m_receiveModule->setCodec(m_sdpData.m_codecs[targetCodec]->payload);
		//m_sendModule->start();
		m_receiveModule->start();

	}
	
	
	
	return result;

}

void SdpModule::parseSdpLine(char * sdpLine)
{
	char type = sdpLine[0];
	istringstream * is;
	char * strPointer;
	string dummy,dummy2;
	int codecNr;
	CodecData * codecData;

	// value
	switch(type)
	{
	case 'v': 
		m_otherSdpData.version =  atoi(sdpLine+2);
		break;
	case 'o': 
		strPointer = sdpLine+2;
		is = new istringstream(strPointer);
		*is >> m_otherSdpData.username >> m_otherSdpData.sessionId >> m_otherSdpData.sessionVersion >> dummy >> dummy >> m_otherSdpData.baseIP;
		delete is;
		break;
	case 's': 
		strPointer = sdpLine+2;
		m_otherSdpData.sessionName = strPointer;
		break;
	case 'c': 
		// 2 kere ofwa? :-)		
		break;
	case 't':
		strPointer = sdpLine+2;
		is = new istringstream(strPointer);
		*is >>	m_otherSdpData.startTime >> m_otherSdpData.stopTime;
		break;
	case 'm':
		
		strPointer = sdpLine+2;
		is = new istringstream(strPointer);
		*is >> dummy >> m_otherSdpData.audioPort >> dummy;

		//codex opvragen
		codecNr = -1;
		*is >> codecNr;

		while(codecNr != -1 )
		{
			codecData = new CodecData;
			codecData->payload = codecNr;
			m_otherSdpData.m_codecs.push_back(codecData);

			codecNr = -1;
			*is >> codecNr;
			
		}
		break;
	case 'a':
		strPointer = sdpLine+2;
		is = new istringstream(strPointer);
		*is >> dummy >> dummy2; // later te coderen om strtok te bewaren van hogere functie
		codecPars.push_back(dummy + " " + dummy2);
		delete is;

		break;

	}

	

	
}